package core.util.logging;

import core.proto.AllComponents;
import core.proto.InfoViz;
import core.proto.Util;
import core.util.logging.constants.Action;
import core.util.logging.constants.Location;
import core.util.logging.screen.ScreenCapture;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Hashtable;

import org.apache.commons.io.FilenameUtils;

import static app.constants.CollabVizConstants.*;

/**
 */
public class UserLogWriter {

	private static String userLogFolderPath;
	public static String timeStamp;

	private static final String LOG_FORMATTER = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s";
	private static final String CHAT_FORMATTER = "%s,%s,%s,%s,%s,%s";
	private static final String STICKY_FORMATTER = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s";

	private static BufferedWriter out;
	
	private static BufferedWriter outChat;
	
	private static BufferedWriter outSticky;
	
	public static String lastElement = "";
	
	public static String lastHover = "";
	
	private static ArrayList<ChatLog> chatList = new ArrayList<ChatLog>();

	/**
	+ * Whether to capture screen shots. 
	 */	
	private static boolean screenCapFlag = false;

	static{
		try {
			userLogFolderPath = new File(LOG_FOLDER).getPath();
			
			String userLogFilePath = Util.generateLogFilePath(USER_LOG_FILE_NAME);
			String userChatFilePath = Util.generateLogFilePath(USER_CHAT_FILE_NAME);
			String userStickyFilePath = Util.generateLogFilePath(USER_STICKY_FILE_NAME);

			out = new BufferedWriter( new FileWriter( userLogFilePath, false ) );
			outChat = new BufferedWriter( new FileWriter( userChatFilePath, false ) );
			outSticky = new BufferedWriter( new FileWriter( userStickyFilePath, false ) );

			Runtime.getRuntime().addShutdownHook(new Thread(){
				public void run(){
					try {
						out.close();
						outChat.close();
						outSticky.close();
					} catch (IOException e) { /* ignore */ }
				}
			});
		} catch (IOException e) {
			throw new Error(e);
		}  
	}



	/**
	 * Toggles screen capture mode. 
	 * @param screenCap
	 */
	public static void setScreenCap( boolean screenCap ) {
		screenCapFlag = screenCap;
	}

	public static void log2( Object action, String uiArea, String objectAffected, String objectName, String searchText, 
			String docHighlight, String annoStatus, String annoText) {
		objectName = delimText(objectName);
		searchText = delimText(searchText);
		docHighlight = delimText(docHighlight);
		annoText = delimText(annoText);
		
		Date now = new Date(System.currentTimeMillis());
		timeStamp = Long.toString(System.currentTimeMillis());
		String user = InfoViz.UserID;
		String condition = InfoViz.condition + "";
		
		String mouseEntry = "no";
		String keyEntry = "no";
		String mouseAction = "null";
		String keyAction = "null";
		
		if(action == Action.KEYTYPE || action== Action.KEYCOPY || action == Action.KEYPASTE){
			keyEntry = "yes";
			keyAction = action.toString();
		}
		else{
			mouseEntry = "yes";
			mouseAction = action.toString();
		}
		
		String activeDoc = FilenameUtils.getBaseName(AllComponents.getCurrentPath());
		
		if( screenCapFlag ) {
			ScreenCapture.takeScreenShot( FilenameUtils.concat(userLogFolderPath, timeStamp ));
		}
		// Time, Action, Object, Area
		String line = String.format( LOG_FORMATTER, Util.formatDate(now), user, condition, mouseEntry, mouseAction, keyEntry, keyAction, uiArea, objectAffected, objectName, searchText, docHighlight, annoStatus, annoText, activeDoc);
		try {
			synchronized(out){
				out.write( line );
				out.newLine();
				out.flush();
			}
			System.out.println( line);
		} catch( IOException e ) {
			e.printStackTrace();
		}
		
		if(action == Action.CLICK || action == Action.DOUBLECLICK){
			if(!lastElement.equals(uiArea)){
				lastElement = uiArea;
				
				if(!chatList.isEmpty()){
					chatLog(uiArea);
				}
			}
		}
		
		if(!lastHover.equals(uiArea)){
			lastHover = uiArea;
			System.out.println("setting hover " + uiArea);
		}
	}
	
	public static void addToChatLog(String user, String chatText, String activeDoc) {
		timeStamp = Long.toString(System.currentTimeMillis());
		Date now = new Date(System.currentTimeMillis());
		
		user = delimText(user);
		chatText = delimText(chatText);
		activeDoc = delimText(activeDoc);
		
		chatList.add(new ChatLog(Util.formatDate(now), user, chatText, activeDoc, lastElement));
	}
	
	public static void chatLog(String uiArea) {
	
		for(ChatLog c : chatList){
			String line = String.format( CHAT_FORMATTER, c.getTimestamp(), c.getUser(), c.getChatText(), c.getActiveDoc(), c.getLastFrame(), uiArea);
			
			try {
				synchronized(outChat){
					outChat.write( line );
					outChat.newLine();
					outChat.flush();
				}
				System.out.println( line);
			} catch( IOException e ) {
				e.printStackTrace();
			}
		}
		
		chatList.clear();
	}
	
	public static void stickyLog(String user, Object action, boolean self, String sticky_id, String sticky_text, String group_id, String sticky_context){
		Date now = new Date(System.currentTimeMillis());
		timeStamp = Long.toString(System.currentTimeMillis());
		String condition = InfoViz.condition + "";
		
		user = delimText(user);
		sticky_text = delimText(sticky_text);
		
		String mouseEntry = "no";
		String keyEntry = "no";
		String mouseAction = "null";
		String keyAction = "null";
		
		if(action == Action.KEYTYPE || action== Action.KEYCOPY || action == Action.KEYPASTE){
			keyEntry = "yes";
			keyAction = action.toString();
		}
		else{
			mouseEntry = "yes";
			mouseAction = action.toString();
		}
		
		String selfString;
		
		if(self){
			selfString = "yes";
		}
		else{
			selfString = "no";
		}
		
		String activeDoc = FilenameUtils.getBaseName(AllComponents.getCurrentPath());
		
		// Time, Action, Object, Area
				String line = String.format( STICKY_FORMATTER, Util.formatDate(now), InfoViz.UserID, condition, mouseEntry+"", mouseAction, selfString, sticky_id, sticky_text, group_id, keyEntry, keyAction, sticky_context, activeDoc);
				try {
					synchronized(outSticky){
						outSticky.write( line );
						outSticky.newLine();
						outSticky.flush();
					}
					System.out.println( line);
				} catch( IOException e ) {
					e.printStackTrace();
				}
				
	}

	// Legacy version, referenced in some places in the code. 
	// Commented out to enable eventual refactoring of these areas of the code.  
	public static void log( String objectAffected, Location uiArea, Object action ) {
		/*
		Date now = new Date(System.currentTimeMillis());
		timeStamp = Long.toString(System.currentTimeMillis());

		if( screenCapFlag ) {
			ScreenCapture.takeScreenShot( FilenameUtils.concat(userLogFolderPath, timeStamp ));
		}
		// Time, Action, Object, Area
		String line = String.format( LOG_FORMATTER, Util.formatDate(now), action.toString(), objectAffected, uiArea);
		try {
			out.write( line );
			out.newLine();
			out.flush();
			//System.out.println( line );
		} catch( IOException e ) {
			e.printStackTrace();
		}
		 */	}
	
	public static String delimText(String in){
		String out = in;
		
		out = out.replace(',', '.');
		out = out.replace("\r\n", " /n ");
		return out;
	}
}
